package com.jackrain.nea.omslocal.Dao;


import com.alibaba.dubbo.common.utils.NetUtils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.util.TypeUtils;
import com.jackrain.nea.config.PropertiesConf;
import com.jackrain.nea.omslocal.service.LocalLogService;
import com.jackrain.nea.omslocal.service.SendMqServies;
import com.jackrain.nea.omslocal.util.JsonKeyCheck;
import com.jackrain.nea.omslocal.util.RegexDateUtil;
import com.jackrain.nea.util.ApplicationContextHandle;
import com.jackrain.nea.util.Tools;
import com.jackrain.nea.util.Validator;
import com.jackrain.nea.web.query.QueryEngine;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.ParseException;
import java.util.*;

/**
 * 保存分销退单数据
 * Description:
 * Created with IntelliJ IDEA.
 * User: cs
 * Date: 2017/4/2
 * Time: 15:49
 */
@Component
@Slf4j
public class TaoBaoFXRefundDao {

    @Autowired
    private RegexDateUtil regexDate;
    private FastDateFormat fastformat = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss");
    @Autowired
    private LocalLogService localLogService;

    @Autowired
    private SendMqServies sendMq;


    /**
     * 保存淘宝分销退单数据方法
     *
     * @param taobaoorderArr
     * @param topic
     */
    public void refundStart(JSONArray taobaoorderArr, String msgkey, String topic) throws Exception {
        TaoBaoFXRefundDao taoBaoFXRefundDao = ApplicationContextHandle.getBean(TaoBaoFXRefundDao.class);
        PropertiesConf pconf = (PropertiesConf) ApplicationContextHandle.getBean("propertiesConf");
        // 定义接收消费日志信息的 jsonobject
        JSONObject infoObj = new JSONObject();
        List tids = new ArrayList();
        int countFaild = 0;
        Long sub_order_id = 0L;
        //获取参数表更新字段
        JsonKeyCheck checkjson = (JsonKeyCheck) ApplicationContextHandle.getBean(JsonKeyCheck.class);

        //  退单业务么没有明细表,直接新增主表或更新主表
        for (Object obj : taobaoorderArr) {
            JSONObject tempObj = new JSONObject();
            try {
                // 循环遍历拿到单条分销退单数据
                JSONObject tempJson = JSONObject.parseObject(obj.toString(), Feature.OrderedField);
                tempObj = tempJson.getJSONObject("jdp_response").getJSONObject("fenxiao_refund_get_response").getJSONObject("refund_detail");

                // 根据唯一外键判
                sub_order_id = tempObj.getLong("sub_order_id");
                Object outId = null;
                // 根据 sub_order_id 查询数据库,判断该数据是 新增 或是 修改
                String selectSql = "SELECT id FROM T_OMSFENXIAOREFUND WHERE sub_order_id = ?";
                int id = Tools.getInt(QueryEngine.getInstance().doQueryOne(selectSql, new Object[]{sub_order_id}),-1);
                if (id < 0) {
                    // 新增数据
                    // 数据不为空 保存数据
                    taoBaoFXRefundDao.insert(tempObj);

                    // 保存消费的详细数据
                    localLogService.insertLogDeatail(tempObj,sub_order_id, 1, topic,msgkey);

                } else {

                        taoBaoFXRefundDao.update(tempObj, id);
                        // 保存消费的详细数据
                    localLogService.insertLogDeatail(tempObj, sub_order_id, 2, topic, msgkey);

                }
                tids.add(sub_order_id);
            } catch (Exception e) {
                // 处理异常  1.将错误信息发送到线上  2. 将错误信息保存到本地数据库
                // 逐条将错误信息以消息发送到线上发送到线上
                // 获取 流
                StringWriter sw = new StringWriter();
                PrintWriter pw = new PrintWriter(sw);

                JSONObject errObj = new JSONObject();
                errObj.put("bus_id",sub_order_id);
                errObj.put("tablename",pconf.getProperty("ons.fxrefund"));
                errObj.put("topic",topic);
                errObj.put("tag",pconf.getProperty("ons.comp"));
                errObj.put("msgkey",msgkey);
                // 线下消费报错的主机 ip
                errObj.put("client_ip", NetUtils.getLocalAddress());
                // 将错误以流写出
                e.printStackTrace(pw);
                errObj.put("errmsg", sw.toString());
                errObj.put("protime",System.currentTimeMillis());
                errObj.put("code",-1);
                sendMq.sendMqinfoObj(errObj, pconf.getProperty("ons.loginfor.err.topic"), pconf.getProperty("ons.loginfor.err.tag"));

                countFaild++;
                localLogService.insertLog(e.getMessage(), tempObj, sub_order_id, topic,msgkey);
                log.debug(e.getMessage());

            }
            // 调用更新线上日志的服务
            infoObj.put("msgkey", msgkey);
            infoObj.put("topic", topic);
            infoObj.put("countsuccess", (taobaoorderArr.size() - countFaild));
            infoObj.put("protime", System.currentTimeMillis());
            infoObj.put("client_ip",  NetUtils.getLocalAddress());
            infoObj.put("tids", tids);
            infoObj.put("code",0);
            infoObj.put("total",taobaoorderArr.size());
            // 消费完成,将消费的消息信息发送至线上,更新线上日志表
            // 参数 1 消息体  2 消息 topic  3 消息 tag
            String msgId = sendMq.sendMqinfoObj(infoObj, pconf.getProperty("ons.loginfor.suf.topic"), pconf.getProperty("ons.loginfor.suf.tag"));
            if("-1".equals(msgId)){
                for(int i = 0; i < 3; i++){
                    if(!"-1".equals(msgId)){
                        break;
                    }
                    //重试回执
                    msgId = sendMq.sendMqinfoObj(infoObj, pconf.getProperty("ons.loginfor.suf.topic"), pconf.getProperty("ons.loginfor.suf.tag"));
                }
            }
            log.debug("taobaofxrefund消费完成回执 msgId= {}, topic= {}, tag= {}", msgId, pconf.getProperty("ons.loginfor.suf.topic"), pconf.getProperty("ons.loginfor.suf.tag"));
        }
    }

    @Transactional
    public void insert(JSONObject tempObj) throws Exception {
        Object outId = null;
        // 新增数据
        // 数据不为空 保存数据
        if (!tempObj.isEmpty()) {
            Map map = null;
            map = saveFxRefund(tempObj);
            outId = map.get("seq");
        } else {
            log.debug("主表数据为空");
        }
        // 在执行完之后需要更改主表的 istrans 字段为 0
        String sql = "update T_OMSFENXIAOREFUND SET istrans = 0 WHERE id = ?";
        QueryEngine.getInstance().executeUpdate(sql, new Object[]{outId});

    }

    @Transactional
    public void update(JSONObject tempObj, int id ) throws Exception {

        // 根据查询到的 id 更新主表数据
        this.updateFxRefund(tempObj, id);

        // 更新操作之后需要更新 istrans 为0
        String sql = "update T_OMSFENXIAOREFUND SET istrans = 0 WHERE id = ?";
        QueryEngine.getInstance().executeUpdate(sql, new Object[]{id});

    }

    /**
     * 保存分销退单主表
     *
     * @param jsonObj
     * @return
     * @throws SQLException
     */

    public Map saveFxRefund(JSONObject jsonObj) throws SQLException, ParseException {

        JsonKeyCheck checkjson = (JsonKeyCheck) ApplicationContextHandle.getBean(JsonKeyCheck.class);
        jsonObj = checkjson.checkJsonkeycache(jsonObj, "T_OMSFENXIAOREFUND", checkjson.getInsertcolsmap());

        Map map = new HashMap();

        // 将固定需要维护的字段加入 jsonObj,  creatTime, modified , outstatus
        // outstatus 默认值为 1 ,当主表所有明细更新完成,将此状态更改为 2;
        Date nowDate = new Date();
        Timestamp nowTime = new Timestamp(nowDate.getTime());

        // 获取主表的 sequences
        String squnceSql = "select get_wsequences('T_OMSFENXIAOREFUND') as SEQ from dual";
        Long id = TypeUtils.castToLong(QueryEngine.getInstance().doQueryOne(squnceSql));

        Object descobj = jsonObj.get("desc");
        jsonObj.remove("desc");
        jsonObj.put("refund_desc", descobj);
        jsonObj.put("id", id);
        jsonObj.put("modified", nowTime);

        String columnName = "";
        String columnValue = "";
        Set set = jsonObj.keySet();
        Object[] objArr = jsonObj.values().toArray();

        for (Object obj1 : set) {
            columnName = columnName + "," + obj1;
        }
        columnName = columnName.substring(1);

        for (int i = 0; i < objArr.length; i++) {

            if (objArr[i] instanceof String) {
                if (regexDate.regexDate(((String) objArr[i]))) {
                    Date date = fastformat.parse(((String) objArr[i]));
                    objArr[i] = date;
                }
            }
            columnValue = columnValue + ",?";
        }

        columnValue = columnValue.substring(1);

        String sql = "insert into T_OMSFENXIAOREFUND (" + columnName + ") values (" + columnValue + ")";

        int code = QueryEngine.getInstance().executeUpdate(sql, objArr);

        map.put("code", code);
        map.put("seq", id);
        return map;
    }


    /**
     * 更新分销退单主表
     *
     * @param jsonObj
     * @return
     * @throws SQLException
     */

    public Map updateFxRefund(JSONObject jsonObj, int id) throws SQLException, ParseException {

        JsonKeyCheck checkjson = (JsonKeyCheck) ApplicationContextHandle.getBean(JsonKeyCheck.class);

        jsonObj = checkjson.checkJsonkeycache(jsonObj, "T_OMSFENXIAOREFUND", checkjson.getUpdatecolsmap());

        Map map = new HashMap();
        // 将固定需要维护的字段加入  modified
        Date nowdate = new Date();
        Timestamp nowTime = new Timestamp(nowdate.getTime());
        jsonObj.put("modified", nowTime);

        // desc 为关键字
        Object descobj = jsonObj.get("desc");
        jsonObj.remove("desc");
        jsonObj.put("refund_desc", descobj);

        String params = "";
        Set set = jsonObj.keySet();
        Object[] objArr = jsonObj.values().toArray();
        for (Object obj1 : set) {
            Object tempobject = jsonObj.get(obj1);
            params = params + "" + obj1 + " = ?,";
        }
        params = params.substring(0, params.length() - 1);

        for (int i = 0; i < objArr.length; i++) {

            if (Validator.isNull(objArr[i])) {
                objArr[i] = "null";
            }
            if (objArr[i] instanceof String) {
                if (regexDate.regexDate(((String) objArr[i]))) {
                    Date date2 = fastformat.parse(((String) objArr[i]));
                    objArr[i] = date2;
                }
            }
        }

        String sql = "update T_OMSFENXIAOREFUND set " + params + " where id = ?";

        int code = QueryEngine.getInstance().executeUpdate(sql, ArrayUtils.add(objArr, id));

        return map;
    }


}
